package com.czx.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.czx.common.constants.RedisKeys;
import com.czx.common.utils.EmailUtils;
import com.czx.common.utils.PasswordUtils;
import com.czx.common.utils.R;
import com.czx.common.utils.RandomCodeUtil;
import com.czx.dto.ResetPwdDto;
import com.czx.entity.MyPage;
import com.czx.common.exception.BlogException;
import com.czx.common.constants.ResponseCode;
import com.czx.dto.EmaiDto;
import com.czx.entity.OldPassword;
import com.czx.entity.User;
import com.czx.common.exception.UsernameException;
import com.czx.mapper.OldPasswordMapper;
import com.czx.mapper.UserMapper;
import com.czx.service.UserService;
import com.czx.service.UserTokenService;
import com.czx.vo.UserToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;


@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private OldPasswordMapper oldPasswordMapper;

    @Autowired
    private UserTokenService userTokenService;
    @Autowired
    private EmailUtils emailUtils;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    @Override
    public Integer updatePassword(OldPassword oldPassword, User user) {
        oldPassword.setUid(user.getId());
        //判断2次密码是否一致
        if (oldPassword.getNewPassword().equals(oldPassword.getRePassword())) {
            if (user == null) {
                throw new UsernameException(ResponseCode.FAIL.getCode(), "用户不存在");
            } else {
                //检查新密码是否和历史密码一致
                QueryWrapper queryWrapper = new QueryWrapper();
                queryWrapper.eq("uid", oldPassword.getUid());
                List<OldPassword> list = oldPasswordMapper.selectList(queryWrapper);
                System.out.println(list);
                boolean flag = false;
                //遍历历史密码是否和新密码相同
                for (OldPassword op : list) {
                    boolean checkpw = PasswordUtils.checkpw(oldPassword.getNewPassword(), op.getOldPassword());
                    System.out.println("1");
                    flag = checkpw;
                }
                if (flag) {
                    System.out.println("2");
                    throw new UsernameException(ResponseCode.FAIL.getCode(), "不能输入历史密码");
                } else {
                    //更新用户密码
                    System.out.println("3");
                    user.setPassword(PasswordUtils.hashpw(oldPassword.getNewPassword()));
                    System.out.println();
                    int i = baseMapper.updateById(user);
                    oldPassword.setOldPassword(user.getPassword());

                    //把历史密码存到旧密码表
                    oldPasswordMapper.insert(oldPassword);
                    return i;
                }
            }
        } else {
            throw new UsernameException(ResponseCode.FAIL.getCode(), "2次密码不相同");
        }
    }

    @Override
    public UserToken login(String username, String password) {
        //根据用户名查询用户是否存在
        User user = getUserByUsername(username);
        if (user == null) {
            throw new UsernameException(ResponseCode.NOT_EXISTS_LOGIN.getCode(), ResponseCode.NOT_EXISTS_LOGIN.getMsg());
        }
        //数据库获得的密码
        String dbpw = user.getPassword();
        if (!PasswordUtils.checkpw(password, dbpw)) {
            throw new BlogException(1001, "用户名或密码错误");
        }
        //账号是否激活
        if (user.getStatus() == 0) {
            throw new BlogException(1002, "账号未激活");

        }
        // 4.创建一个userToken
        UserToken userToken = userTokenService.createUserToken(user);
        // 5.返回userTOken给Controller
        return userToken;
    }

    //个人主页
    @Override
    public User getInfoById(Integer id) {
        return baseMapper.selectById(id);
    }

    /**
     * 注册
     */
    @Override
    public Integer doRegister(User user) {
        User getToUser = getUserByUsername(user.getUsername());
        if (getToUser != null) {
            throw new UsernameException(ResponseCode.EXISTS_LOGIN.getCode(), ResponseCode.EXISTS_LOGIN.getMsg());
        }

        //加密
        user.setPassword(PasswordUtils.hashpw(user.getPassword()));
        //设置激活状态
        user.setStatus(0);
        //设置激活码
        user.setActivationCode(UUID.randomUUID().toString().replaceAll("-", ""));
        //入库
        userMapper.insert(user);

        //发送邮箱
        EmaiDto emaiDto = new EmaiDto();
        emaiDto.setToUser(user.getEmail());
        emaiDto.setTitle("激活链接");
        emaiDto.setContent("<a href = \"http://127.0.0.1:8080/active?code=" + user.getActivationCode() + "\">激活</a>");
        emailUtils.sendEmail(emaiDto);
        return 200;
    }


    /**
     * 获取关注的人的所有信息
     */
    @Override
    public MyPage getFollowById(Integer id, MyPage page) {
        String followKey = String.format(RedisKeys.USER_FOLLOWER_KEY, id);
        Set<String> follows = stringRedisTemplate.opsForZSet().range(followKey, 0, -1);
        //判断follows是否为空，若为空，给follows初始化
        if (follows.size() == 0) {
            follows.add("0");
        }
        List<Integer> followIds = new ArrayList<>();
        for (String follow : follows) {
            followIds.add(Integer.valueOf(follow));
        }

        //获取每一个id的用户信息并封装到page里面
        page = baseMapper.getByIds(page, followIds);
        return page;
    }

    /**
     * 重置密码
     * @param resetPwdDto
     * @return
     */
    @Override
    public R resetPwd(ResetPwdDto resetPwdDto) {
        System.out.println(resetPwdDto);
        User user = getUserByUsername(resetPwdDto.getUsername());

        //判断密码是否和旧密码相同
        if (PasswordUtils.checkpw(resetPwdDto.getPassword(), user.getPassword())) {
            return R.fail("新密码不能和历史密码相同");
        }
        //用emailKey来判断code是否正确
        String emailKey = String.format(RedisKeys.USER_EMAIL_KEY, user.getId());
        String code = stringRedisTemplate.opsForValue().get(emailKey);
        System.out.println("code:" + code);
        String emailCode = resetPwdDto.getEmailCode();
        if (!code.equals(emailCode)) {
            return R.fail("验证码错误");
        }
        //更新数据库密码
        baseMapper.updateById(user);
        return R.success("修改成功");
    }

    /**
     * 发送邮箱用来重置密码
     * @param username
     * @return
     */
    @Override
    public R sendEmailCodeForResetPwd(String username) {
        User user = getUserByUsername(username);
        if (user == null) {
            throw new UsernameException(ResponseCode.FAIL.getCode(), "用户名不存在");
        }
        //生成验证密码的key
        System.out.println("发送请求");
        ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
        String emailKey = String.format(RedisKeys.USER_EMAIL_KEY, user.getId());
        String code = RandomCodeUtil.generateRandomCode(4);
        opsForValue.set(emailKey, code, 60, TimeUnit.SECONDS);


        //发送邮件
        EmaiDto emaiDto = new EmaiDto();
        emaiDto.setToUser(user.getEmail());
        emaiDto.setTitle("重置密码验证");
        emaiDto.setContent("<h3>此验证码用于重置密码，请妥善管理，请勿泄露</h3>" +
                "<h1>验证码：" + code + "</h1>");
        emailUtils.sendEmail(emaiDto);
        return R.success("发送成功");
    }

    /**
     * 查看粉丝的信息
     * @param id
     * @param page
     * @return
     */
    @Override
    public MyPage getFansById(Integer id, MyPage page) {
        String fansKey = String.format(RedisKeys.USER_FANS_KEY, id);
        Set<String> fans = stringRedisTemplate.opsForZSet().range(fansKey, 0, -1);
        //判断粉丝是否为空，若为空初始化
        if (fans.size() == 0) {
            fans.add("0");
        }
        List<Integer> fanIds = new ArrayList<>();
        for (String fan : fans) {
            fanIds.add(Integer.valueOf(fan));
        }
        //获取每一个id的用户信息并封装到page里面
        page = baseMapper.getByIds(page, fanIds);
        return page;
    }

    /**
     * 通过email获取用户信息
     * @param email
     * @return
     */
    public User getUserByEmail(String email) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("email", email);
        return baseMapper.selectOne(queryWrapper);
    }
     @Override
    public User getUserByUsername(String username) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("username", username);
        return baseMapper.selectOne(queryWrapper);
    }

    public User getUserById(Integer id) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("id", id);
        return baseMapper.selectOne(queryWrapper);
    }


}
